<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    
    <title>XRecord 示例 | jouyouyun&#39;s blog</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="description" content="最近在做快捷键绑定的项目，但在绑定单按键时发现 XGrabKey 无法处理。遂请教组长，得知 XRecord 可以处理，于是就去查找 XRecord 的相关资料，但却很少。
所以在此记录一下整理的示例代码，以便日后查看，其功能在代码注释中写出。">
    <meta name="generator" content="Hugo 0.105.0">
    
    
    
    
      <meta name="robots" content="noindex, nofollow">
    

    
<link rel="stylesheet" href="/ananke/css/main.min.css" >



    
    
    
      

    

    
    
    <meta property="og:title" content="XRecord 示例" />
<meta property="og:description" content="最近在做快捷键绑定的项目，但在绑定单按键时发现 XGrabKey 无法处理。遂请教组长，得知 XRecord 可以处理，于是就去查找 XRecord 的相关资料，但却很少。
所以在此记录一下整理的示例代码，以便日后查看，其功能在代码注释中写出。" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://jouyouyun.github.io/post/xrecord-example/" /><meta property="article:section" content="post" />
<meta property="article:published_time" content="2014-04-18T17:42:15+08:00" />
<meta property="article:modified_time" content="2019-02-12T14:37:01+08:00" />

<meta itemprop="name" content="XRecord 示例">
<meta itemprop="description" content="最近在做快捷键绑定的项目，但在绑定单按键时发现 XGrabKey 无法处理。遂请教组长，得知 XRecord 可以处理，于是就去查找 XRecord 的相关资料，但却很少。
所以在此记录一下整理的示例代码，以便日后查看，其功能在代码注释中写出。"><meta itemprop="datePublished" content="2014-04-18T17:42:15+08:00" />
<meta itemprop="dateModified" content="2019-02-12T14:37:01+08:00" />
<meta itemprop="wordCount" content="465">
<meta itemprop="keywords" content="xtst,xrecord," /><meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="XRecord 示例"/>
<meta name="twitter:description" content="最近在做快捷键绑定的项目，但在绑定单按键时发现 XGrabKey 无法处理。遂请教组长，得知 XRecord 可以处理，于是就去查找 XRecord 的相关资料，但却很少。
所以在此记录一下整理的示例代码，以便日后查看，其功能在代码注释中写出。"/>

	
  </head>

  <body class="ma0 avenir bg-near-white">

    
   
  

  <header>
    <div class="bg-black">
      <nav class="pv3 ph3 ph4-ns" role="navigation">
  <div class="flex-l justify-between items-center center">
    <a href="/" class="f3 fw2 hover-white no-underline white-90 dib">
      
        jouyouyun&#39;s blog
      
    </a>
    <div class="flex-l items-center">
      

      
        <ul class="pl0 mr3">
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/post/" title="Archives 页">
              Archives
            </a>
          </li>
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/tags/" title="Tags 页">
              Tags
            </a>
          </li>
          
          <li class="list f5 f4-ns fw4 dib pr3">
            <a class="hover-white no-underline white-90" href="/categories/" title="Categories 页">
              Categories
            </a>
          </li>
          
        </ul>
      
      
<div class="ananke-socials">
  
    <a href="https://github.com/jouyouyun" target="_blank" class="github ananke-social-link link-transition stackoverflow link dib z-999 pt3 pt0-l mr1" title="GitHub link" rel="noopener" aria-label="follow on GitHub——Opens in a new window">
      
        <span class="icon"><svg style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <path d="M256,32C132.3,32,32,134.8,32,261.7c0,101.5,64.2,187.5,153.2,217.9c11.2,2.1,15.3-5,15.3-11.1   c0-5.5-0.2-19.9-0.3-39.1c-62.3,13.9-75.5-30.8-75.5-30.8c-10.2-26.5-24.9-33.6-24.9-33.6c-20.3-14.3,1.5-14,1.5-14   c22.5,1.6,34.3,23.7,34.3,23.7c20,35.1,52.4,25,65.2,19.1c2-14.8,7.8-25,14.2-30.7c-49.7-5.8-102-25.5-102-113.5   c0-25.1,8.7-45.6,23-61.6c-2.3-5.8-10-29.2,2.2-60.8c0,0,18.8-6.2,61.6,23.5c17.9-5.1,37-7.6,56.1-7.7c19,0.1,38.2,2.6,56.1,7.7   c42.8-29.7,61.5-23.5,61.5-23.5c12.2,31.6,4.5,55,2.2,60.8c14.3,16.1,23,36.6,23,61.6c0,88.2-52.4,107.6-102.3,113.3   c8,7.1,15.2,21.1,15.2,42.5c0,30.7-0.3,55.5-0.3,63c0,6.1,4,13.3,15.4,11C415.9,449.1,480,363.1,480,261.7   C480,134.8,379.7,32,256,32z"/>
</svg>
</span>
      
<span class="new-window"><svg  height="8px"  style="enable-background:new 0 0 1000 1000;" version="1.1" viewBox="0 0 1000 1000"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<path d="M598 128h298v298h-86v-152l-418 418-60-60 418-418h-152v-86zM810 810v-298h86v298c0 46-40 86-86 86h-596c-48 0-86-40-86-86v-596c0-46 38-86 86-86h298v86h-298v596h596z" style="fill-rule:evenodd;clip-rule:evenodd;"/>
</svg>
</span></a>
  
</div>

    </div>
  </div>
</nav>

    </div>
  </header>



    <main class="pb7" role="main">
      
  
  <article class="flex-l flex-wrap justify-between mw8 center ph3">
    <header class="mt4 w-100">
      <aside class="instapaper_ignoref b helvetica tracked">
          
        POSTS
      </aside>
      










  <div id="sharing" class="mt3 ananke-socials">
    
  </div>


      <h1 class="f1 athelas mt3 mb1">XRecord 示例</h1>
      
      <p class="tracked">
         <strong>jouyouyun</strong>
      </p>
      
      
      
      <time class="f6 mv4 dib tracked" datetime="2014-04-18T17:42:15+08:00">四月 18, 2014</time>
      

      
      
    </header>
    <div class="nested-copy-line-height lh-copy serif f4 nested-links mid-gray pr4-l w-two-thirds-l"><p>最近在做快捷键绑定的项目，但在绑定单按键时发现 <code>XGrabKey</code> 无法处理。遂请教组长，得知 <code>XRecord</code> 可以处理，于是就去查找 <code>XRecord</code> 的相关资料，但却很少。
所以在此记录一下整理的示例代码，以便日后查看，其功能在代码注释中写出。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * XRecord 是 XLib 的一个扩展，在 xtst 中。
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * 此程序用来监听按键、鼠标点击和鼠标移动事件
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;glib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;X11/Xlib.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;X11/Xlibint.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;X11/extensions/record.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> _RecordEventInfo {
</span></span><span style="display:flex;"><span>        Display <span style="color:#f92672">*</span>ctrl_disp; <span style="color:#75715e">// 控制通道
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        Display <span style="color:#f92672">*</span>data_disp; <span style="color:#75715e">// 数据通道
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        XRecordRange <span style="color:#f92672">*</span>range;
</span></span><span style="display:flex;"><span>        XRecordContext context;
</span></span><span style="display:flex;"><span>} RecordEventInfo;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">union</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span> type; <span style="color:#75715e">// 事件类型
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        xEvent xe; <span style="color:#75715e">// 事件
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>} RecordDate;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">record_init</span> ();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">record_finalize</span> ();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">record_event_cb</span> (XPointer user_data, XRecordInterceptData <span style="color:#f92672">*</span>hook);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> gpointer <span style="color:#a6e22e">enable_ctx_thread</span> (gpointer user_data);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>GMainLoop <span style="color:#f92672">*</span>loop<span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> RecordEventInfo <span style="color:#f92672">*</span>grab_info <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">record_init</span> ()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        grab_info <span style="color:#f92672">=</span> g_new0 (RecordEventInfo, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>grab_info ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Alloc RecordEventInfo memory failed...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp <span style="color:#f92672">=</span> XOpenDisplay (NULL);
</span></span><span style="display:flex;"><span>        grab_info<span style="color:#f92672">-&gt;</span>data_disp <span style="color:#f92672">=</span> XOpenDisplay (NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp <span style="color:#f92672">||</span> <span style="color:#f92672">!</span>grab_info<span style="color:#f92672">-&gt;</span>data_disp ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Unable to connect to X server...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        gint dummy;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>XQueryExtension (grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp, <span style="color:#e6db74">&#34;XTEST&#34;</span>,
</span></span><span style="display:flex;"><span>                                   <span style="color:#f92672">&amp;</span>dummy, <span style="color:#f92672">&amp;</span>dummy, <span style="color:#f92672">&amp;</span>dummy) ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;XTest extension missing...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>XRecordQueryVersion (grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp, <span style="color:#f92672">&amp;</span>dummy, <span style="color:#f92672">&amp;</span>dummy) ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Failed to obtain xrecord version...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        grab_info<span style="color:#f92672">-&gt;</span>range <span style="color:#f92672">=</span> XRecordAllocRange ();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>grab_info<span style="color:#f92672">-&gt;</span>range ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Alloc XRecordRange memory failed...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// 定义需要监听的事件范围，具体见 XRecord 文档
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        grab_info<span style="color:#f92672">-&gt;</span>range<span style="color:#f92672">-&gt;</span>device_events.first <span style="color:#f92672">=</span> KeyPress;
</span></span><span style="display:flex;"><span>        grab_info<span style="color:#f92672">-&gt;</span>range<span style="color:#f92672">-&gt;</span>device_events.last <span style="color:#f92672">=</span> MotionNotify;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        XRecordClientSpec spec <span style="color:#f92672">=</span> XRecordAllClients;
</span></span><span style="display:flex;"><span>        grab_info<span style="color:#f92672">-&gt;</span>context <span style="color:#f92672">=</span> XRecordCreateContext (
</span></span><span style="display:flex;"><span>                                                grab_info<span style="color:#f92672">-&gt;</span>data_disp,
</span></span><span style="display:flex;"><span>                                                <span style="color:#ae81ff">0</span>, <span style="color:#f92672">&amp;</span>spec, <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                                                <span style="color:#f92672">&amp;</span>grab_info<span style="color:#f92672">-&gt;</span>range, <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>grab_info<span style="color:#f92672">-&gt;</span>context ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Unable to create context...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        XSynchronize (grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp, TRUE);
</span></span><span style="display:flex;"><span>        XFlush (grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// 创建线程来处理接收到的数据
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        GThread <span style="color:#f92672">*</span>thrd <span style="color:#f92672">=</span> g_thread_new (<span style="color:#e6db74">&#34;enable context&#34;</span>,
</span></span><span style="display:flex;"><span>                                (GThreadFunc)enable_ctx_thread, NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>thrd ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Unable to create thread...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * 释放资源
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">record_finalize</span> ()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>grab_info) {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (grab_info<span style="color:#f92672">-&gt;</span>context) {
</span></span><span style="display:flex;"><span>                XRecordDisableContext(grab_info<span style="color:#f92672">-&gt;</span>data_disp, grab_info<span style="color:#f92672">-&gt;</span>context);
</span></span><span style="display:flex;"><span>                XRecordFreeContext(grab_info<span style="color:#f92672">-&gt;</span>data_disp, grab_info<span style="color:#f92672">-&gt;</span>context);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (grab_info<span style="color:#f92672">-&gt;</span>range) {
</span></span><span style="display:flex;"><span>                XFree(grab_info<span style="color:#f92672">-&gt;</span>range);
</span></span><span style="display:flex;"><span>                grab_info<span style="color:#f92672">-&gt;</span>range <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp) {
</span></span><span style="display:flex;"><span>                XCloseDisplay (grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp);
</span></span><span style="display:flex;"><span>                grab_info<span style="color:#f92672">-&gt;</span>ctrl_disp <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (grab_info<span style="color:#f92672">-&gt;</span>data_disp) {
</span></span><span style="display:flex;"><span>                XCloseDisplay (grab_info<span style="color:#f92672">-&gt;</span>data_disp);
</span></span><span style="display:flex;"><span>                grab_info<span style="color:#f92672">-&gt;</span>data_disp <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (grab_info) {
</span></span><span style="display:flex;"><span>                g_free (grab_info);
</span></span><span style="display:flex;"><span>                grab_info <span style="color:#f92672">=</span> NULL;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> gpointer
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">enable_ctx_thread</span> (gpointer user_data)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// 开始接收数据
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">if</span> ( <span style="color:#f92672">!</span>XRecordEnableContext (grab_info<span style="color:#f92672">-&gt;</span>data_disp,
</span></span><span style="display:flex;"><span>                                        grab_info<span style="color:#f92672">-&gt;</span>context,
</span></span><span style="display:flex;"><span>                                        record_event_cb, NULL) ) {
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Unable to enable context...&#34;</span>);
</span></span><span style="display:flex;"><span>                record_finalize ();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        g_thread_exit (NULL);
</span></span><span style="display:flex;"><span>        g_main_loop_quit(loop);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> NULL;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">record_event_cb</span> (XPointer user_data, XRecordInterceptData <span style="color:#f92672">*</span>hook)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ( hook<span style="color:#f92672">-&gt;</span>category <span style="color:#f92672">!=</span> XRecordFromServer ) {
</span></span><span style="display:flex;"><span>                XRecordFreeData(hook);
</span></span><span style="display:flex;"><span>                g_warning (<span style="color:#e6db74">&#34;Data not from X server...&#34;</span>);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        RecordDate <span style="color:#f92672">*</span>data <span style="color:#f92672">=</span> (RecordDate <span style="color:#f92672">*</span>)hook<span style="color:#f92672">-&gt;</span>data;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> detail <span style="color:#f92672">=</span> data<span style="color:#f92672">-&gt;</span>xe.u.u.detail; <span style="color:#75715e">// 按键或鼠标的 keycode
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">int</span> event_type <span style="color:#f92672">=</span> data<span style="color:#f92672">-&gt;</span>type; <span style="color:#75715e">// 事件类型
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#75715e">// 事件发生时的坐标
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">int</span> rootX <span style="color:#f92672">=</span> data<span style="color:#f92672">-&gt;</span>xe.u.keyButtonPointer.rootX;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> rootY <span style="color:#f92672">=</span> data<span style="color:#f92672">-&gt;</span>xe.u.keyButtonPointer.rootY;
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">/*int time = hook-&gt;server_time;*/</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> (event_type) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> KeyPress:
</span></span><span style="display:flex;"><span>                g_print(<span style="color:#e6db74">&#34;%d pressed</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, detail);
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">/*KeySym sym = XKeycodeToKeysym(grab_info-&gt;data_disp, detail, 0);*/</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> KeyRelease:
</span></span><span style="display:flex;"><span>                g_print(<span style="color:#e6db74">&#34;%d released</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, detail);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> MotionNotify:
</span></span><span style="display:flex;"><span>                g_print(<span style="color:#e6db74">&#34;Mouse Motion: %d -- %d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, rootX, rootY);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> ButtonPress:
</span></span><span style="display:flex;"><span>                g_print(<span style="color:#e6db74">&#34;Mouse %d pressed</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, detail);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> ButtonRelease:
</span></span><span style="display:flex;"><span>                g_print(<span style="color:#e6db74">&#34;Mouse %d released</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, detail);
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        XRecordFreeData(hook);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>argv[])
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>        record_init();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        loop <span style="color:#f92672">=</span> g_main_loop_new(NULL, FALSE);
</span></span><span style="display:flex;"><span>        g_main_loop_run(loop);
</span></span><span style="display:flex;"><span>        g_main_loop_unref(loop);
</span></span><span style="display:flex;"><span>        record_finalize();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul class="pa0">
  
   <li class="list di">
     <a href="/tags/xtst" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">xtst</a>
   </li>
  
   <li class="list di">
     <a href="/tags/xrecord" class="link f5 grow no-underline br-pill ba ph3 pv2 mb2 dib black sans-serif">xrecord</a>
   </li>
  
</ul>
<div class="mt6 instapaper_ignoref">
      
      
      </div>
    </div>

    <aside class="w-30-l mt6-l">




</aside>

  </article>

    </main>
    <footer class="bg-black bottom-0 w-100 pa3" role="contentinfo">
  <div class="flex justify-between">
  <a class="f4 fw4 hover-white no-underline white-70 dn dib-ns pv2 ph3" href="https://jouyouyun.github.io" >
    &copy;  jouyouyun 2023 
  </a>
    <div>
<div class="ananke-socials">
  
    <a href="https://github.com/jouyouyun" target="_blank" class="github ananke-social-link link-transition stackoverflow link dib z-999 pt3 pt0-l mr1" title="GitHub link" rel="noopener" aria-label="follow on GitHub——Opens in a new window">
      
        <span class="icon"><svg style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <path d="M256,32C132.3,32,32,134.8,32,261.7c0,101.5,64.2,187.5,153.2,217.9c11.2,2.1,15.3-5,15.3-11.1   c0-5.5-0.2-19.9-0.3-39.1c-62.3,13.9-75.5-30.8-75.5-30.8c-10.2-26.5-24.9-33.6-24.9-33.6c-20.3-14.3,1.5-14,1.5-14   c22.5,1.6,34.3,23.7,34.3,23.7c20,35.1,52.4,25,65.2,19.1c2-14.8,7.8-25,14.2-30.7c-49.7-5.8-102-25.5-102-113.5   c0-25.1,8.7-45.6,23-61.6c-2.3-5.8-10-29.2,2.2-60.8c0,0,18.8-6.2,61.6,23.5c17.9-5.1,37-7.6,56.1-7.7c19,0.1,38.2,2.6,56.1,7.7   c42.8-29.7,61.5-23.5,61.5-23.5c12.2,31.6,4.5,55,2.2,60.8c14.3,16.1,23,36.6,23,61.6c0,88.2-52.4,107.6-102.3,113.3   c8,7.1,15.2,21.1,15.2,42.5c0,30.7-0.3,55.5-0.3,63c0,6.1,4,13.3,15.4,11C415.9,449.1,480,363.1,480,261.7   C480,134.8,379.7,32,256,32z"/>
</svg>
</span>
      
<span class="new-window"><svg  height="8px"  style="enable-background:new 0 0 1000 1000;" version="1.1" viewBox="0 0 1000 1000"  xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<path d="M598 128h298v298h-86v-152l-418 418-60-60 418-418h-152v-86zM810 810v-298h86v298c0 46-40 86-86 86h-596c-48 0-86-40-86-86v-596c0-46 38-86 86-86h298v86h-298v596h596z" style="fill-rule:evenodd;clip-rule:evenodd;"/>
</svg>
</span></a>
  
</div>
</div>
  </div>
</footer>

  </body>
</html>
